import React, { useEffect, useRef, useState } from 'react';
import { EditorState } from '@codemirror/state';
import { EditorView, keymap, Decoration, DecorationSet, ViewPlugin, ViewUpdate } from '@codemirror/view';
import { syntaxHighlighting, HighlightStyle } from '@codemirror/language';
import { tags } from '@lezer/highlight';
import '../styles/variable-textarea.css';

interface VariableTextAreaProps {
  value: string;
  onChange: (value: string) => void;
  rows?: number;
  onCompositionStart?: () => void;
  onCompositionEnd?: (e: React.CompositionEvent<HTMLDivElement>) => void;
}

// 定义变量高亮样式
const myHighlightStyle = HighlightStyle.define([
  { tag: tags.variableName, class: 'cm-variable' }
]);

// 创建变量装饰器
const variableHighlight = ViewPlugin.fromClass(class {
  decorations: DecorationSet;

  constructor(view: EditorView) {
    this.decorations = this.buildDecorations(view);
  }

  update(update: ViewUpdate) {
    if (update.docChanged || update.viewportChanged) {
      this.decorations = this.buildDecorations(update.view);
    }
  }

  buildDecorations(view: EditorView) {
    const decorations: any[] = [];
    const content = view.state.doc.toString();
    let match;
    const regex = /\${([^}]+)}/g;

    while ((match = regex.exec(content)) !== null) {
      const from = match.index;
      const to = from + match[0].length;
      decorations.push(
        Decoration.mark({
          class: 'cm-variable'
        }).range(from, to)
      );
    }

    return Decoration.set(decorations);
  }
}, {
  decorations: v => v.decorations
});

const VariableTextArea: React.FC<VariableTextAreaProps> = ({ 
  value, 
  onChange, 
  rows = 4,
  onCompositionStart,
  onCompositionEnd 
}) => {
  const editorRef = useRef<EditorView | null>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [isComposing, setIsComposing] = useState(false);
  const lastValueRef = useRef(value);

  useEffect(() => {
    if (!containerRef.current) return;

    const startState = EditorState.create({
      doc: value,
      extensions: [
        variableHighlight,
        syntaxHighlighting(myHighlightStyle),
        EditorView.lineWrapping,
        EditorView.updateListener.of((update) => {
          if (update.docChanged) {
            const newValue = update.state.doc.toString();
            if (!isComposing && newValue !== lastValueRef.current) {
              lastValueRef.current = newValue;
              onChange(newValue);
            }
          }
        }),
        EditorView.domEventHandlers({
          compositionstart: () => {
            setIsComposing(true);
            onCompositionStart?.();
            return false;
          },
          compositionend: (e) => {
            setIsComposing(false);
            onCompositionEnd?.({} as React.CompositionEvent<HTMLDivElement>);
            const view = editorRef.current;
            if (view) {
              const newValue = view.state.doc.toString();
              if (newValue !== lastValueRef.current) {
                lastValueRef.current = newValue;
                onChange(newValue);
              }
            }
            return false;
          }
        }),
        keymap.of([
          {
            key: 'Enter',
            run: (view: EditorView) => {
              const { state } = view;
              const { selection } = state;
              view.dispatch({
                changes: {
                  from: selection.main.from,
                  to: selection.main.to,
                  insert: '\n'
                },
                selection: {
                  anchor: selection.main.from + 1,
                  head: selection.main.from + 1
                }
              });
              return true;
            }
          },
          {
            key: '/',
            run: (view: EditorView) => {
              const { state } = view;
              const { selection } = state;
              const text = state.sliceDoc(selection.main.from, selection.main.to);
              view.dispatch({
                changes: {
                  from: selection.main.from,
                  to: selection.main.to,
                  insert: `\${${text}}`
                },
                selection: {
                  anchor: selection.main.from + 2,
                  head: selection.main.from + 2
                }
              });
              return true;
            }
          }
        ])
      ]
    });

    const view = new EditorView({
      state: startState,
      parent: containerRef.current
    });

    editorRef.current = view;

    return () => {
      view.destroy();
    };
  }, []);

  useEffect(() => {
    const view = editorRef.current;
    if (view && value !== lastValueRef.current && !isComposing) {
      lastValueRef.current = value;
      view.dispatch({
        changes: {
          from: 0,
          to: view.state.doc.length,
          insert: value
        }
      });
    }
  }, [value, isComposing]);

  return (
    <div 
      ref={containerRef} 
      style={{ 
        flex: 1,
        fontSize: '14px',
        lineHeight: 1.5,
        display: 'flex',
        flexDirection: 'column',
        width: '100%',
        overflow: 'hidden'
      }}
      className="variable-textarea"
    />
  );
};

export default VariableTextArea; 